/**
 * 本工具类 部分依赖uniapp 更换环境 请自行调整
 */

// fmt: 'yyyy-MM-dd hh:mm:ss'    time: new Date(1554780164000)
export function formatDate(fmt, time) {
	const o = {
		'M+': time.getMonth() + 1, // 月份 4
		'd+': time.getDate(), // 日  9
		'h+': time.getHours(), // 小时 11
		'm+': time.getMinutes(), // 分 22
		's+': time.getSeconds(), // 秒 44
		'q+': Math.floor((time.getMonth() + 3) / 3), // 季度
		'S': time.getMilliseconds() // 毫秒
	};
	if (/(y+)/.test(fmt)) {
		// RegExp.$1是RegExp的一个属性,指的是与正则表达式匹配的第一个子匹配
		fmt = fmt.replace(RegExp.$1, (time.getFullYear() + '').substr(4 - RegExp.$1.length)); // 这是转换年
	}
	for (const k in o) {
		if (new RegExp('(' + k + ')').test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ?
				(o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
			// o[k] 4 9 11 22 44
			// '00'+o[k] 004 009 0011 0022 0044
			// ..substr(('' + o[k]).length从o[k].length开始截取
		}
	}
	return fmt; // 2019-04-09 11:22:44
};





/**
 * @param {Object} func 要执行的函数
 * @param {Object} delayed	防抖间隔时间
 * @param {Object} that	要执行函数的this 指向
 * @description  每次调用 debounce(func, delayed, immediate, that) 时 返回一个新的函数
 */
export const debounce = ({
	func,
	delayed = 500,
	immediate = false,
	that
}) => {
	return new function() {
		let timeout = null;
		let loading = false;
		let fn = null;
		if (!fn) fn = func.bind(that);
		let t = {
			clearLoadingStatus: () => {
				loading = false;
			},
			that
		}
		return function(p) {
			if (immediate && loading) return showToast("正在执行该操作，请稍后!!");
			if (!immediate && timeout) clearTimeout(timeout);
			loading = true;
			timeout = setTimeout(() => {
				if (fn) fn(t, p)
				clearTimeout(timeout)
				timeout = null
			}, delayed)
		}
	}
}

/**
 * @param {String[]} list 函数列表
 * @param {Number} delayed	间隔时间
 * @param {Boolean} immediate true:先执行   false:后执行
 * @param {Object} that	this对象
 */
export const debounceFactory = function({
	funcs,
	delayed = 0,
	immediate = false,
	that
}) {
	funcs.forEach(e => {
		that[e] = debounce({
			func: that[e],
			delayed,
			immediate,
			that
		})
	})
}

/**
 * 	@param {Array<Object>} list   一个对象数组  其内参数  ⬇
 *  {require:(boolean类型，校验数据 是否必传)}.   
 *  {mess:("|" 作为分割线 [0]为空时返回消息，[1] 格式异常时返回消息 只有[1]没有时使用[0])}
 * 	{val:(为传入值)}
 *  {reg:(传入规则/内部已有规则名)}
 * 	例子 --> validateData([
					{ require: true, mess: '请到我的页面，进行登陆', val: this.userInfo.id },
					{ require: true, mess: '请输入姓名', val: this.name },
					{ require: true, mess: '请输入手机号|请输入正确手机号', reg: 'mobile', val: this.mobile },
					{ require: true, mess: '请输入身份证号|请输入正确身份证号', reg: 'idCard', val: this.idCard }
				])
	
 *	@return {boolean}
 */
export const validateData = function(list) {
	let rules = new Map([ //规则列表  
		["mobile", /^1[3456789]\d{9}$/], //校验手机号码
		["idCard", /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/], //校验身份证 
		["number", /^[0-9]*$/], //校验是否是数字
		["money", /^\d*\.?\d{1,2}$/]
	]);
	let formException = function(mess) { //校验的异常类
		this.mess = mess
	}
	let type = (p) => { // 返回数据的类型  => Object Array Number String 等 首字母大写
		let full = Object.prototype.toString.call(p)
		return full.substring(8, full.length - 1)
	}
	let regExp = (p) => { //返回正则表达式，在 rules 列表中存在即返回  不存在则为自定义规则
		return rules.get(p) || p
	};
	list.forEach(e => {
		// 目前就用到这些  没有去封装更多
		// 数据必传 且 为空时
		if (e.require && !e.val) {
			throw new formException(e.mess.split('|')[0])
		} else if (e.reg && !regExp(e.reg).test(e.val)) { //正则校验错误
			throw new formException(e.mess.split('|')[1] || e.mess.split('|')[0])
		} else if (e.require && (type(e.val) == 'Array' || Array.isArray(e.val)) && !e.val.length) { //校验Array 类型为空时
			throw new formException(e.mess.split('|')[0])
		}
	})
}

/**
 * @param {Object} currIndex :当前页  pageSize:每页条数	func：执行的函数	that：func的this指向
 * @description  使用示例 ⬇
 * this.pagination = pagination({
		curIndex: 0,
		pageSize: 10,
		func: this.getList,
		that: this
	}).init()->init非必须，链式;
	通过  this.pagination.   next()|prev()|init():一般在初始化时使用
 * 注意: 传入的函数 不要使用箭头函数和方法，要使用 function
 */
export const pagination = function({
	curIndex = 0,
	pageSize = 10,
	func,
	that
}) {
	let config = { //下列所需用到的配置
		curIndex, //当前页码  默认为0
		pageSize, //每页数量  默认为10
		loading: false, //当前加载状态
		pageCount: 0, //总页数 请求时传入总条数 进行计算
		total: 0, //总条数 请求时传入总条数
		fn: func.bind(that), //初始化时改变this的指向为使用页面的vm
		that // 传入的 this指向
	}

	let t = { //回传给函数的操作  
		setTotal: (num) => { //第一次执行时需要用户去设置 total
			if (num != config.total) {
				config.total = num
				config.pageCount = Math.ceil(parseInt(num) / config.pageSize);
			}
		},
		clearLoadingStatus: () => { //当为前置执行时  需要用户在执行完后 清楚loading 状态
			config.loading = false
		},
		setCurIndex: (i) => {
			config.curIndex = i
		}
	}
	return new function(p) {
		this.next = () => {
			// if (config.curIndex + 1 >= config.pageCount) return showToast('已到底');
			this.to(config.curIndex + 1)
		}
		this.prev = () => {
			if (config.curIndex < 1) return;
			this.to(config.curIndex - 1)
		}
		this.to = (i) => {
			if (config.loading) return showToast('正在加载下一页,请等待...');
			config.loading = true;
			config.curIndex = i;
			t['curIndex'] = config.curIndex
			t['pageSize'] = config.pageSize
			t['pageCount'] = config.pageCount
			config.fn(t, p)
		}
		this.init = () => {
			return this.to(0), this;
		}
	}
}
